package com.pmmaster.service.Impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.pmmaster.common.api.Result;
import com.pmmaster.common.entitis.Admin;
import com.pmmaster.common.entitis.AdminPermission;
import com.pmmaster.common.entitis.AdminRoleInfo;
import com.pmmaster.common.utils.*;
import com.pmmaster.core.mapper.AdminMapper;
import com.pmmaster.core.mapper.AdminMenuMapper;
import com.pmmaster.core.mapper.AdminPermissionMapper;
import com.pmmaster.core.mapper.AdminRoleInfoMapper;
import com.pmmaster.service.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class AdminServiceImpl implements AdminService {
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private AdminRoleInfoMapper roleInfoMapper;
    @Autowired
    private AdminMenuMapper menuMapper;
    @Autowired
    private AdminPermissionMapper permissionMapper;

    @Override
    public Admin getLoginUser(HttpServletRequest request, String tokenHead, String tokenHeader) {
        String token = request.getHeader(tokenHeader);
        if (StringUtil.isBlank(token) || !token.startsWith(tokenHead)) {
            return null;
        }
        token = token.substring(tokenHead.length());// The part after "Bearer "
        Admin admin = (Admin) redisUtil.get(token);
        if (admin == null) {
            if (!StringUtil.isBlank(token)) {
                Integer admin_id = jwtTokenUtil.getUserIdFromToken(token);
                if (admin_id != null && admin_id > 0) {
                    admin = adminMapper.selectByPrimaryKey(admin_id);
                    redisUtil.set(token, admin, 300);
                }
            }
        }
        return admin;
    }

    @Override
    public Result save(HttpServletRequest request, Admin admin) {
        admin.setPassword(BCrypt.hashpw(admin.getPassword(), BCrypt.gensalt()));
        if (admin.getId() != null && admin.getId() > 0) {
            // 更新
            admin.setUpdatedAt(new Date());
            return adminMapper.updateByPrimaryKeySelective(admin) > 0 ? Result.success("", "更新成功") : Result.failed("更新失败");
        } else {
            // 保存
            if (adminMapper.getLoginUser(admin.getPhone()) != null) {
                return Result.failed("手机号：" + admin.getPhone() + "已被注册");
            }
            if (adminMapper.getLoginUser(admin.getName()) != null) {
                return Result.failed("账号：" + admin.getName() + "已经存在了");
            }
            admin.setNowLoginAt(new Date());
            admin.setCreatedAt(admin.getNowLoginAt());
            admin.setUpdatedAt(admin.getNowLoginAt());
            admin.setLastLoginAt(admin.getNowLoginAt());
            admin.setNowLoginIp(CommonUtil.getIpAddr(request));
            admin.setLastLoginIp(admin.getNowLoginIp());
            admin.setState(1);
            admin.setAvatar("");
            return adminMapper.insertSelective(admin) > 0 ? Result.success("", "添加成功") : Result.failed("添加失败");
        }
    }

    @Override
    public Result login(Admin admin, String tokenHead) {
        if (!StringUtil.isBlank(admin.getToken())) {
            if (redisUtil.get(admin.getToken()).equals(admin.getCode())) {
                Admin member = adminMapper.getLoginUser(admin.getName());
                if (member == null) {
                    return Result.failed("账户不存在");
                }
                if (BCrypt.checkpw(admin.getPassword(), member.getPassword())) {
                    String token = jwtTokenUtil.generateToken(member.getId());
                    return Result.success(tokenHead + token, "登录成功");
                }
                return Result.failed("密码有误");
            }
            return Result.failed("图片验证码有误");
        }
        return Result.failed("非法登录");
    }

    @Override
    public Map<String, Object> userPermissionInfo(Admin user, List<Integer> list) {
        String key = "permission_info:" + user.getId().toString() + user.getNowLoginAt();
        Map<String, Object> map = (Map<String, Object>) redisUtil.get(key);
        if (map == null) {
            map = new HashMap<>();
            map.put("menus", TreeUtil.handleMenuTree(menuMapper.getUserMenuList(user.getId())));
            List<AdminPermission> permissionList = permissionMapper.getUserPermissionList(user.getId());
            List<String> permission_route = new ArrayList<>();
            List<String> operate_permission = new ArrayList<>();
            for (AdminPermission permission : permissionList) {
                permission_route.add(permission.getValue());
                operate_permission.add(permission.getAlias());
            }
            map.put("permission_route", permission_route);
            map.put("operate_permission", operate_permission);
            map.put("is_super", list.contains(user.getId()));
            redisUtil.set(key, map, 600);
        }
        return map;
    }

    @Override
    public Page<Admin> getList(Admin admin) {
        PageHelper.startPage(admin.getPage(), admin.getPageSize());
        Page<Admin> page = adminMapper.list(admin);
        for (Admin user : page) {
            List<AdminRoleInfo> list = roleInfoMapper.getRoleInfo(user.getId());
            List<Integer> role_list = new ArrayList<>();
            for (AdminRoleInfo info : list) {
                user.setRole(user.getRole() + info.getRoleName() + " | ");
                role_list.add(info.getRoleId());
            }
            user.setRoleList(role_list.toArray(new Integer[0]));
        }
        return page;
    }

    @Override
    public Result info(Integer id) {
        Admin admin = adminMapper.selectByPrimaryKey(id);
        admin.setRoleList(roleInfoMapper.queryUserRole(admin.getId()).toArray(new Integer[0]));
        return Result.success(admin);
    }

    @Override
    public Result auth(Admin admin) {
        roleInfoMapper.deleteByUser(admin.getId());
        for (Integer role_id : admin.getRoleList()) {
            roleInfoMapper.insertSelective(new AdminRoleInfo(admin.getId(), role_id));
        }
        return Result.success(null, "授权成功");
    }

    @Override
    public Result updatePass(Admin admin) {
        Admin user = new Admin();
        user.setId(admin.getId());
        user.setUpdatedAt(new Date());
        user.setPassword(BCrypt.hashpw(admin.getPassword(), BCrypt.gensalt()));
        return Result.optionResult(adminMapper.updateByPrimaryKeySelective(user));
    }

    @Override
    public Result delete(Admin admin) {
        Admin user = new Admin();
        user.setId(admin.getId());
        user.setUpdatedAt(new Date());
        user.setState(admin.getState());
        return Result.optionResult(adminMapper.updateByPrimaryKeySelective(user));
    }

    @Override
    public boolean checkPermission(HttpServletRequest request, Integer[] super_users) {
        Admin admin = (Admin) request.getSession().getAttribute("loginUser");
        if (admin != null) {
            if (Arrays.asList(super_users).contains(admin.getId())) {
                //超管
                return true;
            } else {
                //普通管理员，校验权限
                List<String> permissionList = (List<String>) userPermissionInfo(admin, new ArrayList<>()).get("permission_route");
                AntPathMatcher path = new AntPathMatcher();
                for (String reg : permissionList) {
                    if (path.match(reg, "/" + request.getRequestURI())) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
